#include <args.hpp>
#include <function.hpp>
#include <cstring>
using namespace ants::args;

args::args(int argc, const char **argcv) {
    std::string title, value;
    char *find, type, **argv = (char **)argcv;
    int i, shift;
    int64_t hash;
    
    title = "", type = ' ';
    value = argv[0];
    hash = hash1(title.c_str()) + hash2(title.c_str());
    this->arglst[hash] = argitem(title, value, type);
    for(i = 1; i < argc; ++i) {
        if(argv[i][0] == '-'){
            if(argv[i][1] == '-') {
                type = '=';
                find = strchr(argv[i], '=');
                shift = 2;
            } else if(argv[i][1] != '\0') {
                type = '-';
                find = strchr(argv[i], ':');
                shift = 1;
            } else {
                title = argv[i];
                type = '*';
                hash = hash1(title.c_str()) + hash2(title.c_str());
                this->arglst[hash] = argitem(title, "", type);
                continue;
            }
            if(find == NULL) {
                title = argv[i] + shift;
                value = "";
            } else {
                value = std::string(find + 1);
                title = std::string(argv[i] + shift, find - (argv[i] + shift));
            }
            hash = hash1(title.c_str()) + hash2(title.c_str());
            this->arglst[hash] = argitem(title, value, type);
        } else if(argv[i][0] == '@') {
            find = strchr(argv[i], '=');
            if(find == NULL) {
                title = argv[i] + 1;
                value = "";
            } else {
                title = std::string(argv[i] + 1, find - argv[i] - 1);
                value = std::string(find + 1);
            }
            this->arglst[hash1(title.c_str()) + hash2(title.c_str())] = argitem(title, value, '@');
        } else {
            title = std::string("  NO TITLE  ") + argv[i];
            this->arglst[hash1(title.c_str()) + hash2(title.c_str())] = argitem("", argv[i], '*');
        }
    }
}
bool args::hasArg(const std::string &title) const {
    int64_t hash = hash1(title.c_str()) + hash2(title.c_str());
    return this->arglst.find(hash) != this->arglst.end();
}
args::~args() {
    this->arglst.clear();
}
const std::unordered_map<int64_t, argitem> &args::getArgs() const {
    return this->arglst;
}
const argitem &args::getArg(const std::string &title) const {
    int64_t hash = hash1(title.c_str()) + hash2(title.c_str());
    std::unordered_map<int64_t, argitem>::const_iterator it = this->arglst.find(hash);
    if(it == this->arglst.end())
        throw std::runtime_error("Argument not found");
    return it->second;
}
size_t args::getArgCount() const {
    return this->arglst.size();
}

argitem::argitem(const std::string &title, const std::string &value, char type) {
    this->title = title;
    this->value = value;
    this->type = type;
}
argitem::argitem() {
    this->title = "";
    this->value = "";
    this->type = '*';
}
argitem::~argitem() {
    this->title.clear();
    this->value.clear();
}
std::string argitem::getTitle() const {
    return this->title;
}
std::string argitem::getValue() const {
    return this->value;
}
char argitem::getType() const {
    return this->type;
}
